<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
  <title>动态数据源日志信息服务项目</title>
  <link rel="icon" href="static/favicon.ico" type="image/x-icon"/>
  <link href="https://cdn.bootcss.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet" />
  <style>
    [v-cloak]{
      display: none;
    }
    pre {outline: 1px solid #ccc; padding: 5px; margin: 5px; height: 500px;}
    .string { color: green; }
    .number { color: darkorange; }
    .boolean { color: blue; }
    .null { color: magenta; }
    .key { color: red; }

  </style>
</head>
<body>
<!--这里是给打war包的时候用的,在运行main函数的时候也指向了这里-->

<div class="d-flex flex-column flex-md-row align-items-center p-3 px-md-4 mb-3
bg-white border-bottom shadow-sm">
  <h5 class="my-0 mr-md-auto font-weight-normal">
    <img style="width:200px;" alt="404" src="static/img/404.png" />
    动态数据源日志信息服务项目webapp
    <small>
      version：1.0.1
    </small>
  </h5>
  <nav class="my-2 my-md-0 mr-md-3">
    <!--<a class="p-2 text-dark" href="#">Features</a>-->
    <!--<a class="p-2 text-dark" href="#">Enterprise</a>-->
    <!--<a class="p-2 text-dark" href="#">Support</a>-->
    <!--<a class="p-2 text-dark" href="#">Pricing</a>-->

  </nav>
  <!--<button style="margin-bottom: 17px;" class="btn btn-outline-primary">查询</button>-->
</div>

<div class="pricing-header px-3 py-3 pt-md-5 pb-md-4 mx-auto text-center">
  <h1 class="display-4">日志解析数据API 展示</h1>
  <p class="lead">日志解析结果数据查询API，数据来源于各单位上传的或者主动收割的日志解析结果文件。</p>
</div>

<div class="container" id="info-area">

  <div class="row">
    <div class="col-md-9">
      <input type="text" class="form-control" id="api-path" placeholder="api信息" value="" v-model="currentApiInfo" />
      <br />
      <pre id="response">响应全文</pre>
    </div>
    <div class="col-md-3">
      <select id="database" class="form-control" @change="changeDb()">
        <option value="-1">请选择日志所属网站</option>
        <template v-for="item in dbs">
          <option value="{{item.id}}">{{item.name}}</option>
        </template>
      </select>
      <br />
      <select id="rest-api-select" class="form-control" @change="changeApi()">
        <option value="-1">请选择查看的数据</option>
        <template v-for="(index,item) in apis">
          <option value="{{index}}">{{item.name}}</option>
        </template>
      </select>
      <br />
      <div class="row">
        <div class="col-md-6 mb-3">
          <select id="month" class="form-control" @change="changeMonth()">
            <option value="-1">选择月份</option>
            <template v-for="item in months">
              <option value="{{item}}">
                {{item}}
              </option>
            </template>
          </select>
        </div>
        <div class="col-md-6 mb-3">
          <select id="year" class="form-control" @change="changeYear()">
            <option value="-1">选择年份</option>
            <template v-for="item in years">
              <option value="{{item}}">{{item}}</option>
            </template>
          </select>
        </div>
      </div>
      <button style="margin-bottom: 17px;" class="btn btn-outline-primary" @click="executeQuery()">查询</button>
    </div>
  </div>
   <br />
  <p>若是有分页，分页的数据页码是固定的，查询的时候，一般现在数据库有的数据是2017年的，平台1也有2016年数据，其他的参数请自行制定！</p>
  <div>
    <pre id="api-info-area"></pre>
  </div>
  <hr />
  <div style="background-color: #b8daff;">
    <h5 style="color: #005cbf;">
      &radic;API说明
    </h5>
    <p>
      请求数据说明：项目的根路径是在服务端设置的，本项目为api。请求的参数有id，begin，offset，type这四个，id是必须的。其中type也是每个都会有的，默认是month，
      除了在摘要查询中需要指定外，其他的都不用，
      基本支持get和post请求，但是post的数据最终都会转为querystring。
      返回数据由code和body组成。
      <code lang="json">
        {
        meta:{code:int，msg:string},
        body:object
        }
      </code>
    </p>
    <h5 style="color: #005cbf">&radic;日志解析结果上传与收割说明</h5>
    <p>
      在新版本的共享网的建设中，不直接对日志进行收集，各机构负责自己平台的日志的解析，然后将解析结果上传到共享网。
      由共享网对日志解析的结果数据进行入库存储，然后再统一进行日志数据的公示。日志的解析工具由共享网提供，而解析入库
      的程序也由共享网提供，各机构可下载进行尝试或者搭建自己的日志服务；
      其中对于日志的收割策略暂时还未有规定。
      故而暂定在开始的时候是主动上传解析结果，而后期再次优化的时候增加主动收割的策略。
      主动收割的拿日志解析结果数据是通过logstash监控文件的变化，而后传输至es，再由es进行文本的生成。
      生成文本之后通过aw2sql来进行结果解析入库。
    </p>

    <hr />
  </div>
  <div class="card-deck mb-3 text-center">
      <div class="card mb-4 shadow-sm">
        <div class="card-header">
          <h4 class="my-0 font-weight-normal">日志解析工具</h4>
        </div>
        <div class="card-body">
          <h1 class="card-title pricing-card-title">awstats</h1>
          <ul class="list-unstyled mt-3 mb-4">
            <li>本地执行</li>
            <li>安全快速</li>
          </ul>
          <a target="_blank" class="btn btn-lg btn-block btn-outline-primary"
             href="http://www.awstats.org/">项目主页</a>
        </div>
      </div>
      <div class="card mb-4 shadow-sm">
        <div class="card-header">
          <h4 class="my-0 font-weight-normal">解析结果入库工具</h4>
        </div>
        <div class="card-body">
          <h1 class="card-title pricing-card-title">aw2sql </h1>
          <ul class="list-unstyled mt-3 mb-4">
            <li>文本数据结构化</li>
            <li>存入mysql，可以与任意项目整合</li>
          </ul>
          <a class="btn btn-lg btn-block btn-outline-primary" href="https://github.com/zw231212/aw2sql"
             target="_blank">项目主页</a>
        </div>
      </div>
      <div class="card mb-4 shadow-sm">
        <div class="card-header">
          <h4 class="my-0 font-weight-normal">数据API服务项目</h4>
        </div>
        <div class="card-body">
          <h1 class="card-title pricing-card-title">log-analytics </h1>
          <ul class="list-unstyled mt-3 mb-4">
            <li>多数据源</li>
            <li>REST API服务</li>
          </ul>
          <a class="btn btn-lg btn-block btn-outline-primary"
             href="https://github.com/zw231212/log-analytics" target="_blank">项目主页</a>
        </div>
      </div>
    </div>

  <footer class="pt-4 my-md-5 pt-md-5 border-top">
    <div class="row">
      <div class="col-12 col-md">
        <img class="mb-2" src="static/favicon.ico" alt="" width="24" height="24">
        <small class="d-block mb-3 text-muted">&copy; 国家科技资源共享服务工程技术研究中心2017-2018</small>
      </div>
      <div class="col-6 col-md">
        <h5>Plan</h5>
        <ul class="list-unstyled text-small">
          <li><a class="text-muted" href="#">数据API说明</a></li>
        </ul>
      </div>
      <div class="col-6 col-md">
        <h5>Resources</h5>
        <ul class="list-unstyled text-small">
          <li><a class="text-muted" href="https://escience.org.cn/" target="_blank">项目来源</a></li>
        </ul>
      </div>
      <div class="col-6 col-md">
        <h5>About</h5>
        <ul class="list-unstyled text-small">
          <li><a class="text-muted" target="_blank" href="https://nstr.escience.net.cn/about">关于我们</a></li>
        </ul>
      </div>
    </div>
  </footer>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
<!--<script src="https://cdn.bootcss.com/echarts/4.1.0/echarts.min.js"></script>-->
<script src="static/js/vue/vue.min.js"></script>
<script src="static/js/vue/vue-resource.min.js"></script>
<script>
  var dbs = [{name:"共享杯",id:"share.com"},
    {name:"平台1",id:"2005DKA10100"},
    {name:"科搜气象",id:"kejsoqixiang"},
  ];
  var version = "v1";
  var apis = [
      {
        "name":"获取每月或者每年摘要数据",
        "api":version+"/general/list",
        "params":{//请求参数
          "id":"也就是各平台约定的唯一标号，在日志解析时候就指定的config",
          "begin":"年份，XXXX四位数字来表示,month,月份，不足的用0来补足,day，日期，不足2位的用0来补足，这里的参数是年份+月份+日期，字符串，中间使用横杆“-”来分割",
          "offset":"偏移量，也就是偏移当前月份多少个月，整数，从0开始",
          "type":"类型，每年每月或者每日，分别为year，month"
        },
        "fields":{  //返回数据，摘要数据，每日数据没有
          "yearmonth":"年份和月份",
          "visits":"参观人次",
          "visits_unique":"参观者",
          "pages":"网页数",
          "hits":"文件数",
          "bandwidth":"字节数",
          "pages_nv":"非浏览器网页数",
          "hits_nv":"非浏览器文件数",
          "bandwidth_nv":"非浏览器字节数",
          "hosts_known":"已知的hosts数量",
          "hosts_unknown":"无法解析的hosts数量",
        }
      },
    {
      "name":"获取每月或每年或每日的基本数据",
      "api":version+"/general/daily/list",
      "params":{//请求参数
        "id":"也就是各平台约定的唯一标号，在日志解析时候就指定的config",
        "begin":"年份，XXXX四位数字来表示,month,月份，不足的用0来补足,day，日期，不足2位的用0来补足，这里的参数是年份+月份+日期，字符串，中间使用横杆“-”来分割",
        "offset":"偏移量，也就是偏移当前月份多少个月，整数，从0开始",
        "type":"类型，每年每月或者每日，分别为year，month，day",
        "number":"分页页码",
        "size":"分页大小"
      },
      "fields":{//返回参数字段
        "day":"时间或者月份,或者年份",
        "visits":"参观人次",
        "pages":"网页数",
        "hits":"文件数",
        "bandwidth":"字节数",
      }
    },
    {
     "name":"参观者的区域信息",
      "api":version+"/area/list",
      "params":{
        "id":"也就是各平台约定的唯一标号，在日志解析时候就指定的config",
        "begin":"年份，XXXX四位数字来表示,month,月份，不足的用0来补足,这里的参数是年份+月份，字符串，中间使用横杆“-”来分割",
        "offset":"偏移量，也就是偏移当前月份多少个月，整数，从0开始",
        "number":"分页页码",
        "size":"分页大小"
      },
      "fields":{
        "code":"区域代码，如果是写的ip则是解析失败的标识，如果是cn则表示中国，其他类同（这里需要准备国家简称代码-全称和icon数据由使用者去解决）",
        "pages":"网页数",
        "hits":"文件数",
        "bandwidth":"字节数",
      }
    },
    {
      "name":"参观者的IP信息",
      "api":version+"/host/list",
      "params":{
        "id":"也就是各平台约定的唯一标号，在日志解析时候就指定的config",
        "begin":"年份，XXXX四位数字来表示,month,月份，不足的用0来补足,这里的参数是年份+月份，字符串，中间使用横杆“-”来分割",
        "offset":"偏移量，也就是偏移当前月份多少个月，整数，从0开始",
        "number":"分页页码",
        "size":"分页大小"
      },
      "fields":{
        "host":"ip",
        "pages":"网页数",
        "hits":"文件数",
        "bandwidth":"字节数",
        "lastvisit":"最近参观日期",
      }
    },
    {
      "name":"搜索引擎机器人",
      "api":version+"/robots/list",
      "params":{
        "id":"也就是各平台约定的唯一标号，在日志解析时候就指定的config",
        "begin":"年份，XXXX四位数字来表示,month,月份，不足的用0来补足,这里的参数是年份+月份，字符串，中间使用横杆“-”来分割",
        "offset":"偏移量，也就是偏移当前月份多少个月，整数，从0开始",
        "number":"分页页码",
        "size":"分页大小"
      },
      "fields":{
        "name":"ip",
        "hits":"文件数",
        "bandwidth":"字节数",
        "lastvisit":"最近参观日期",
      }
    },
    {
      "name":"每次参观所花时间",
      "api":version+"/session/list",
      "params":{
        "id":"也就是各平台约定的唯一标号，在日志解析时候就指定的config",
        "begin":"年份，XXXX四位数字来表示,month,月份，不足的用0来补足,这里的参数是年份+月份，字符串，中间使用横杆“-”来分割",
        "offset":"偏移量，也就是偏移当前月份多少个月，整数，从0开始",
      },
      "fields":{
        "yearmonth":"时间信息",
        "range":"查看的时间范围",
        "visits":"查看人数",
      }
    },
    {
      "name":"文件类别",
      "api":version+"/filetypes/list",
      "params":{
        "id":"也就是各平台约定的唯一标号，在日志解析时候就指定的config",
        "begin":"年份，XXXX四位数字来表示,month,月份，不足的用0来补足,这里的参数是年份+月份，字符串，中间使用横杆“-”来分割",
        "offset":"偏移量，也就是偏移当前月份多少个月，整数，从0开始",
      },
      "fields":{
        "yearmonth":"时间信息",
        "type":"文件类别",
        "hits":"文件数",
        "bandwidth":"字节数",
      }
    },
    {
      "name":"网站的参观的URL",
      "api":version+"/pages/list",
      "params":{
        "id":"也就是各平台约定的唯一标号，在日志解析时候就指定的config",
        "begin":"年份，XXXX四位数字来表示,month,月份，不足的用0来补足,这里的参数是年份+月份，字符串，中间使用横杆“-”来分割",
        "offset":"偏移量，也就是偏移当前月份多少个月，整数，从0开始",
        "number":"分页页码",
        "size":"分页大小",
        "action":"获取的类型，是获取全部url还是入站url，还是出站url，也就是分别是：all，entry，exit"
      },
      "fields":{
        "yearmonth":"时间信息",
        "url":"网页信息",
        "pages":"网页数",
        "bandwidth":"字节数",
        "entry":"入站数，如果为0表示不是入站url",
        "exit":"出站数，如果为0表示不是出站url",
      }
    },
    {
      "name":"操作系统数据",
      "api":version+"/os/list",
      "params":{
        "id":"也就是各平台约定的唯一标号，在日志解析时候就指定的config",
        "begin":"年份，XXXX四位数字来表示,month,月份，不足的用0来补足,这里的参数是年份+月份，字符串，中间使用横杆“-”来分割",
        "offset":"偏移量，也就是偏移当前月份多少个月，整数，从0开始",
      },
      "fields":{
        known:{
          "yearmonth":"时间信息",
          "name":"系统名称",
          "hits":"文件数",
        },
        unknown:{
          "yearmonth":"时间信息",
           "agent":"用户代理数据",
           "lastvisit":"最后参观日期"
        }
      }
    },
    {
      "name":"浏览器数据",
      "api":version+"/browser/list",
      "params":{
        "id":"也就是各平台约定的唯一标号，在日志解析时候就指定的config",
        "begin":"年份，XXXX四位数字来表示,month,月份，不足的用0来补足,这里的参数是年份+月份，字符串，中间使用横杆“-”来分割",
        "offset":"偏移量，也就是偏移当前月份多少个月，整数，从0开始"
      },
      "fields":{
        known:{
          "yearmonth":"时间信息",
          "name":"浏览器名称",
          "hits":"文件数",
        },
        unknown:{
          "yearmonth":"时间信息",
          "agent":"用户代理数据",
          "lastvisit":"最后参观日期"
        }

      }
    },
    {
      "name":"错误统计数据",
      "api":version+"/error/list",
      "params":{
        "id":"也就是各平台约定的唯一标号，在日志解析时候就指定的config",
        "begin":"年份，XXXX四位数字来表示,month,月份，不足的用0来补足,这里的参数是年份+月份，字符串，中间使用横杆“-”来分割",
        "offset":"偏移量，也就是偏移当前月份多少个月，整数，从0开始",
      },
      "fields":{
        "yearmonth":"时间信息",
        "code":"错误码",
        "hits":"文件数",
        "bandwidth":"字节数",
      }
    },
    {
      "name":"错误详情数据",
      "api":version+"/error/detail",
      "params":{
        "id":"也就是各平台约定的唯一标号，在日志解析时候就指定的config",
        "begin":"年份，XXXX四位数字来表示,month,月份，不足的用0来补足,这里的参数是年份+月份，字符串，中间使用横杆“-”来分割",
        "offset":"偏移量，也就是偏移当前月份多少个月，整数，从0开始",
        "number":"分页页码",
        "size":"分页大小",
        "code":"错误码，有404，403还有400的数据"
      },
      "fields":{
        "yearmonth":"时间信息",
        "url":"错误码",
        "hits":"文件数",
        "referer":"来源",
      }
    },
    {
      "name":"下载的文件的信息数据",
      "api":version+"/downloads/list",
      "params":{
        "id":"也就是各平台约定的唯一标号，在日志解析时候就指定的config",
        "begin":"年份，XXXX四位数字来表示,month,月份，不足的用0来补足,这里的参数是年份+月份，字符串，中间使用横杆“-”来分割",
        "offset":"偏移量，也就是偏移当前月份多少个月，整数，从0开始",
        "number":"分页页码",
        "size":"分页大小"
      },
      "fields":{
        "yearmonth":"时间信息",
        "url":"错误码",
        "downloads":"x下载数",
        "hits":"文件数",
        "bandwidth":"字节数",
      }
    }
  ];
  var infoVm = new Vue({
    el:"#info-area",
    data:{
      months:Array(12).fill('naive').map((v, i) =>{ return i+1}),
      years:Array(12).fill('naive').map((v, i) =>{ return 2007+i}),
      dbs:dbs,
      apis:apis,
      year:2017,
      month:5,
      currentApi:apis[0],
      currentDbId:dbs[0].id,
      type:"month",
      responseInfo:"",
      currentApiInfo:""
    },
    ready: function () {
      changeApiInfoArea(this.currentApi);
      this.currentApiInfo = this.apiInfo;
    },
    computed:{
        apiInfo:function(){
           var baseApi = this.currentApi.api;
           var begin = this.year +"-" + this.month,type = this.type,id=this.currentDbId;
           var params = {
             id:id,
             begin:begin,
             offset:0,
             type:  type
           };
           let querystring = json2Querystring(params);
           return baseApi+"?"+querystring;
        }
    },
    methods:{
       changeDb:function(){
         let value = $("#database option:selected").val();
         if(value == -1){
           return;
         }
         this.currentDbId = value;
         this.currentApiInfo = this.apiInfo;
       },
      changeApi:function(){
        let value = $("#rest-api-select option:selected").val();
        if(value == -1){
          return;
        }
        this.currentApi = this.apis[value];
        this.currentApiInfo = this.apiInfo;
      },
      changeMonth:function(){
        let value = $("#month option:selected").val();
        if(value == -1){
          return;
        }
        this.month = value;
        this.currentApiInfo = this.apiInfo;
      },
      changeYear:function(){
        let value = $("#year option:selected").val();
        if(value == -1){
          return;
        }
        this.year = value;
        this.currentApiInfo = this.apiInfo;
      },
      executeQuery:function(){
         this.$http.get(this.currentApiInfo).then(function (resp) {
           changeResponseInfoArea(resp.data);
           changeApiInfoArea(this.currentApi)
        },function (err) {
          console.log(err)
        })
      }
    }
  });

  function changeResponseInfoArea(json){
    $('#response').html(syntaxHighlight(json));
  }

  function changeApiInfoArea(json){
    $('#api-info-area').html(syntaxHighlight(json));
  }

  //将json数据转换为querystring
  function json2Querystring(data) {
    try {
      var tempArr = [];
      for (var i in data) {
        var key = encodeURIComponent(i);
        var value = encodeURIComponent(data[i]);
        tempArr.push(key + '=' + value);
      }
      var urlParamsStr = tempArr.join('&');
      return urlParamsStr;
    } catch (err) {
      return '';
    }
  }


  //格式化显示json数据
  function syntaxHighlight(json) {
    if (typeof json != 'string') {
      json = JSON.stringify(json, undefined, 2);
    }
    json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
    return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function(match) {
      var cls = 'number';
      if (/^"/.test(match)) {
        if (/:$/.test(match)) {
          cls = 'key';
        } else {
          cls = 'string';
        }
      } else if (/true|false/.test(match)) {
        cls = 'boolean';
      } else if (/null/.test(match)) {
        cls = 'null';
      }
      return '<span class="' + cls + '">' + match + '</span>';
    });
  }
</script>
</body>
</html>
